#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <semaphore.h>
#include <fcntl.h>

#define ITERATIONS 100000  // 每个子进程竞争信号量的次数

// 用于计算时间差
long long get_time_diff(struct timeval start, struct timeval end) {
    return (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
}

// 子进程执行的函数
void child_process(sem_t *sem, int id) {
    struct timeval start_time, end_time;
    long long total_time = 0;

    for (int i = 0; i < ITERATIONS; i++) {
        // 记录开始时间，进行第一次信号量等待
        gettimeofday(&start_time, NULL);
        sem_wait(sem);  // 等待信号量
        gettimeofday(&end_time, NULL);
        total_time += get_time_diff(start_time, end_time);

        // 记录结束时间，进行信号量释放
        gettimeofday(&start_time, NULL);
        sem_post(sem);  // 释放信号量
        gettimeofday(&end_time, NULL);
        total_time += get_time_diff(start_time, end_time);
    }

    // 输出子进程的总信号量竞争时间和平均时间
    printf("Child %d: Total time (microseconds): %lld\n", id, total_time);
    printf("Child %d: Average time per operation: %lld microseconds\n", id, total_time / (2 * ITERATIONS));
    exit(0);  // 子进程结束
}

int main() {
    sem_t *sem;  // 信号量
    pid_t pid1, pid2;
    struct timeval start_time, end_time;
    long long total_time = 0;

    // 创建并初始化信号量
    sem = sem_open("/test_semaphore", O_CREAT, 0644, 1);
    if (sem == SEM_FAILED) {
        perror("sem_open failed");
        exit(1);
    }

    // 父进程开始记录时间
    gettimeofday(&start_time, NULL);

    // 创建两个子进程
    pid1 = fork();
    if (pid1 == 0) {
        // 第一个子进程
        child_process(sem, 1);
    }

    pid2 = fork();
    if (pid2 == 0) {
        // 第二个子进程
        child_process(sem, 2);
    }

    // 父进程等待两个子进程完成
    wait(NULL);
    wait(NULL);

    // 父进程记录结束时间
    gettimeofday(&end_time, NULL);
    total_time = get_time_diff(start_time, end_time);

    // 输出父进程的总运行时间
    printf("Parent: Total time (microseconds): %lld\n", total_time);

    // 删除信号量
    sem_close(sem);
    sem_unlink("/test_semaphore");

    return 0;
}

